package com.hexb.core.mybatis

import com.hexb.core.mybatis.entry.SqlEntry
import org.apache.ibatis.mapping.MappedStatement
import org.apache.ibatis.mapping.SqlCommandType
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
import org.apache.ibatis.session.Configuration
import org.apache.log4j.Logger

/**
 * @Package : com.hexb.core.mybatis
 * @Author : hexb 
 * @Date : 2018-08-12 17:56
 */
class SQLUpdateBuilder {

    static final Logger logger = Logger.getLogger(SQLUpdateBuilder.class)
    static final String update = 'update'
    static final String updateByMap = 'updateByMap'
    static final String updateBatch = 'updateBatch'
    static final String updateBatchByMap = 'updateBatchByMap'


    static MappedStatement update(SqlEntry entry, Configuration configuration) {
        update("${entry.namespace}.$update", entry, configuration, entry.entryClass, false)
    }

    static MappedStatement updateByMap(SqlEntry entry, Configuration configuration) {
        update("${entry.namespace}.$updateByMap", entry, configuration, Map.class, false)
    }

    static MappedStatement updateBatch(SqlEntry entry, Configuration configuration) {
        update("${entry.namespace}.$updateBatch", entry, configuration, entry.entryClass, true)
    }

    static MappedStatement updateBatchByMap(SqlEntry entry, Configuration configuration) {
        update("${entry.namespace}.$updateBatchByMap", entry, configuration, Map.class, true)
    }

    static MappedStatement update(String id, SqlEntry entry, Configuration configuration, Class<?> paramType, Boolean batch) {
        try {
            String sql = [updateTable(entry), updateColumns(entry, configuration, batch)].join(' ')
            def sqlSource = new XMLLanguageDriver().createSqlSource(configuration, "<script>${sql}</script>", paramType)
            def msBuilder = new MappedStatement.Builder(configuration, id,
                    sqlSource,
                    SqlCommandType.UPDATE)
            msBuilder.build()
        } catch (e) {
            logger.error(e)
            throw e
        }
    }

    private static String updateTable(SqlEntry entry) {
        "update ${entry.tableName} \n"
    }

    private static String updateColumns(SqlEntry entry, Configuration configuration, Boolean batch) {
        def updateColumns = entry.propertyMapping.findAll { it != entry.idEntry.column && !it.updateIgnore }
        def where = !batch ? "where `${entry.idEntry.column}` = #{${entry.idEntry.property}}" : """
              where `${entry.idEntry.column}` in 
              <foreach collection="ids" separator="," item="item" open="(" close=")">
                #{item}
              </foreach>
            """
        def sql = updateColumns.collect {
            def prefix = batch ? 'entry.' : ''
            """<if test="$prefix${it.property}!=null">
                  `${it.column}` = #{$prefix${it.property}},
               </if>
            """
        }

        """<set> 
                ${sql.join(' ')} 
            </set> $where
        """
    }
}
